package handlers

import (
	"fmt"
	"log"
	"net/http"
	"ota-backend/config"
	"ota-backend/models"
	"ota-backend/storage"
	"path/filepath"
	"time"

	"github.com/gin-gonic/gin"
)

// OTAHandler OTA服务处理器
type OTAHandler struct {
	storage *storage.LocalStorage
}

// NewOTAHandler 创建OTA处理器
func NewOTAHandler(storage *storage.LocalStorage) *OTAHandler {
	return &OTAHandler{
		storage: storage,
	}
}

// CheckUpdate 检查固件更新
func (h *OTAHandler) CheckUpdate(c *gin.Context) {
	// 从JWT中间件获取认证信息
	otaProduct, exists := c.Get("ota_product")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "认证信息不存在"})
		return
	}
	product := otaProduct.(*models.Product)

	otaClaims, exists := c.Get("ota_claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "JWT claims信息不存在"})
		return
	}
	claims := otaClaims.(*OTAClaims)

	var request struct {
		ProductID      string `json:"product_id" binding:"required"`
		CurrentVersion string `json:"current_version" binding:"required"`
		SN             string `json:"sn" binding:"required"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 验证请求参数与JWT信息的一致性
	if request.ProductID != claims.ProductID {
		log.Printf("产品ID不匹配: 请求=%s, JWT=%s", request.ProductID, claims.ProductID)
		c.JSON(http.StatusBadRequest, gin.H{"error": "产品ID不匹配"})
		return
	}

	if request.SN != claims.SN {
		log.Printf("设备SN不匹配: 请求=%s, JWT=%s", request.SN, claims.SN)
		c.JSON(http.StatusBadRequest, gin.H{"error": "设备SN不匹配"})
		return
	}

	log.Printf("找到产品: public_id=%s, product_id=%s, latest_version=%s", request.ProductID, product.ID, product.LatestVersion)

	// 检查设备是否存在，不存在则创建
	var device models.Device
	if err := config.DB.Where("sn = ? AND product_id = ?", request.SN, product.ID).First(&device).Error; err != nil {
		// 创建设备记录
		device = models.Device{
			SN:             request.SN,
			ProductID:      product.ID,
			CurrentVersion: request.CurrentVersion,
			LastCheckTime:  time.Now(),
			Status:         "online",
		}
		if err := config.DB.Create(&device).Error; err != nil {
			log.Printf("创建设备失败: sn=%s, product_id=%s, error=%v", request.SN, product.ID, err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "创建设备记录失败"})
			return
		}
		log.Printf("创建新设备: sn=%s, product_id=%s", request.SN, product.ID)
	} else {
		// 更新设备信息
		device.CurrentVersion = request.CurrentVersion
		device.LastCheckTime = time.Now()
		device.Status = "online"
		if err := config.DB.Save(&device).Error; err != nil {
			log.Printf("更新设备失败: sn=%s, product_id=%s, error=%v", request.SN, product.ID, err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "更新设备信息失败"})
			return
		}
		log.Printf("更新设备信息: sn=%s, product_id=%s, current_version=%s", request.SN, product.ID, request.CurrentVersion)
	}

	// 检查是否有待执行的升级任务
	var task models.Task
	err := config.DB.Where(
		"product_id = ? AND status = 'pending' AND (sn = ? OR sn = '') AND task_type = 'upgrade'",
		product.ID, request.SN,
	).First(&task).Error

	if err != nil {
		log.Printf("没有找到待执行的升级任务: product_id=%s, sn=%s", product.ID, request.SN)
		c.JSON(http.StatusOK, gin.H{
			"need_update": false,
			"message":     "没有待执行的升级任务",
		})
		return
	}

	// 获取任务指定的固件版本信息
	var firmware models.Firmware
	if err := config.DB.Where("product_id = ? AND version = ?", product.ID, task.Version).First(&firmware).Error; err != nil {
		log.Printf("查询固件失败: product_id=%s, version=%s, error=%v", product.ID, task.Version, err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取固件信息失败"})
		return
	}
	log.Printf("找到升级固件: product_id=%s, version=%s, task_id=%s", product.ID, firmware.Version, task.ID)

	// 构建下载URL - 使用数据库中存储的实际文件名
	downloadUrl := firmware.DownloadURL

	c.JSON(http.StatusOK, gin.H{
		"need_update":     true,
		"latest_version":  firmware.Version,
		"current_version": request.CurrentVersion,
		"firmware_info": gin.H{
			"version":      firmware.Version,
			"description":  firmware.Description,
			"file_size":    firmware.FileSize,
			"release_time": firmware.ReleaseTime,
			"download_url": downloadUrl,
		},
		"task_info": gin.H{
			"id":             task.ID,
			"name":           task.Name,
			"execute_time":   task.ExecuteTime,
			"effective_time": task.EffectiveTime,
		},
	})
}

// DownloadFirmware 下载固件（终端调用）
func (h *OTAHandler) DownloadFirmware(c *gin.Context) {
	// 从JWT中间件获取认证信息
	otaClaims, exists := c.Get("ota_claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "JWT claims信息不存在"})
		return
	}
	claims := otaClaims.(*OTAClaims)

	productID := c.Param("product_id")
	filename := c.Param("filename")

	// 验证请求的产品ID与JWT中的产品ID是否一致
	if productID != claims.ProductID {
		log.Printf("下载固件时产品ID不匹配: 请求=%s, JWT=%s", productID, claims.ProductID)
		c.JSON(http.StatusForbidden, gin.H{"error": "无权限下载此产品的固件"})
		return
	}

	// 构建完整的文件路径 - 直接使用产品ID，不再添加files前缀
	filePath := filepath.Join(productID, filename)

	// 检查文件是否存在
	if !h.storage.FileExists(filePath) {
		c.JSON(http.StatusNotFound, gin.H{"error": "固件文件不存在"})
		return
	}

	// 获取文件
	file, err := h.storage.GetFile(filePath)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "文件读取失败"})
		return
	}
	defer file.Close()

	// 设置响应头
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
	c.Header("Content-Type", "application/octet-stream")

	// 发送文件
	c.File(file.Name())
}

// ReportUpgradeStatus 报告升级状态
func (h *OTAHandler) ReportUpgradeStatus(c *gin.Context) {
	// 从JWT中间件获取认证信息
	otaProduct, exists := c.Get("ota_product")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "认证信息不存在"})
		return
	}
	product := otaProduct.(*models.Product)

	otaClaims, exists := c.Get("ota_claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "JWT claims信息不存在"})
		return
	}
	claims := otaClaims.(*OTAClaims)

	var request struct {
		SN        string `json:"sn" binding:"required"`
		ProductID string `json:"product_id" binding:"required"`
		Version   string `json:"version" binding:"required"`
		Status    string `json:"status" binding:"required"` // success, failed
		Message   string `json:"message"`
	}

	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 验证请求参数与JWT信息的一致性
	if request.ProductID != claims.ProductID {
		log.Printf("报告升级状态时产品ID不匹配: 请求=%s, JWT=%s", request.ProductID, claims.ProductID)
		c.JSON(http.StatusBadRequest, gin.H{"error": "产品ID不匹配"})
		return
	}

	if request.SN != claims.SN {
		log.Printf("报告升级状态时设备SN不匹配: 请求=%s, JWT=%s", request.SN, claims.SN)
		c.JSON(http.StatusBadRequest, gin.H{"error": "设备SN不匹配"})
		return
	}

	// 创建升级记录 - 每次升级都创建新记录，保留完整历史
	upgradeRecord := models.UpgradeRecord{
		SN:          request.SN,
		ProductID:   product.ID,
		Version:     request.Version,
		UpgradeTime: time.Now(),
		Status:      request.Status,
		Message:     request.Message,
	}
	if err := config.DB.Create(&upgradeRecord).Error; err != nil {
		log.Printf("创建升级记录失败: sn=%s, version=%s, error=%v", request.SN, request.Version, err)
	} else {
		log.Printf("升级记录已创建: sn=%s, version=%s, status=%s, upgrade_time=%s", request.SN, request.Version, request.Status, upgradeRecord.UpgradeTime.Format("2006-01-02 15:04:05"))
	}

	// 查找并删除对应的任务
	var task models.Task
	err := config.DB.Where(
		"product_id = ? AND version = ? AND status = 'pending' AND (sn = ? OR sn = '') AND task_type = 'upgrade'",
		product.ID, request.Version, request.SN,
	).First(&task).Error

	if err == nil {
		// 找到对应的任务，删除它
		if err := config.DB.Delete(&task).Error; err != nil {
			log.Printf("删除任务失败: task_id=%s, error=%v", task.ID, err)
		} else {
			log.Printf("任务已删除: task_id=%s, task_name=%s", task.ID, task.Name)
		}
	} else {
		log.Printf("未找到对应的pending任务: product_id=%s, version=%s, sn=%s", product.ID, request.Version, request.SN)
	}

	// 如果升级成功，更新设备版本
	if request.Status == "success" {
		var device models.Device
		if err := config.DB.Where("sn = ? AND product_id = ?", request.SN, product.ID).First(&device).Error; err == nil {
			device.CurrentVersion = request.Version
			device.LastCheckTime = time.Now()
			if err := config.DB.Save(&device).Error; err != nil {
				log.Printf("更新设备版本失败: sn=%s, version=%s, error=%v", request.SN, request.Version, err)
			} else {
				log.Printf("设备版本已更新: sn=%s, version=%s", request.SN, request.Version)
			}
		}
	}

	c.JSON(http.StatusOK, gin.H{"message": "升级状态报告成功"})
}

// GetUpgradeRecords 获取升级记录列表
func (h *OTAHandler) GetUpgradeRecords(c *gin.Context) {
	productID := c.Query("product_id")
	sn := c.Query("sn")

	var upgradeRecords []models.UpgradeRecord
	query := config.DB.Preload("Product")

	if productID != "" {
		query = query.Where("product_id = ?", productID)
	}

	if sn != "" {
		query = query.Where("sn = ?", sn)
	}

	if err := query.Order("upgrade_time DESC").Find(&upgradeRecords).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, upgradeRecords)
}
